#include <iostream>



/**
 * 节点
 */
struct ListNode {
    //当前我的值
    int val;
    //下一个节点的地址
    ListNode* next;

    //构造方法
    ListNode(int val) :
        val(val),
        next(NULL) {
    }

};

ListNode* arr[1000005];

//带头单链表结构体
struct List {
    //头节点
    ListNode* head;
    //尾节点
    ListNode* tail;
    //链表大小
    int size;

    //构造方法
    List() : head(NULL), tail(NULL), size(0) {}

    //是否为空
    bool IsEmpty() const {
        return head == NULL;
    }

    //添加节点
    ListNode* Add(int val) {
        ListNode* newNode = new ListNode(val);
        if (head == NULL) {
            head = newNode;
            tail = newNode;
        }
        else {
            tail->next = newNode;
            tail = newNode;
        }
        size++;
        return newNode;
    }

    //在某个地址后添加节点
    ListNode* Add(int val, ListNode* node){
        ListNode* newNode = new ListNode(val);
        newNode->next = node->next; //新节点的下一个指向当前节点的下一个
        node->next = newNode; //当前节点的下一个指向新节点

        if (node == tail) {
            tail = newNode; //如果是尾节点，更新尾节点
        }
        
        size++;
        return newNode;
    }

    //打印
    void Print() {
        ListNode* cur = head;
        while (cur != NULL) {
            printf("值=[%d],地址=[%p],下一个地址=[%p]\n",
                cur->val, cur, cur->next);
            cur = cur->next;
        }
    }

    //查找
    ListNode* Find(int val) {
        ListNode* cur = head;
        while (cur != NULL) {
            if (cur->val == val) {
                return cur;
            }
            cur = cur->next;
        }
        return NULL; //未找到
    }

    //查找下一个
    int FindNext(int val) {
        if (tail->val == val) {
            return 0; //如果是尾节点，返回0
        }

        ListNode* cur = head;
        while (cur != NULL) {
            if (cur->val == val) {
                return cur->next->val;
            }
            cur = cur->next;
        }
        return 0;
    }


    int FindNext(ListNode* node){
        if (node == NULL || node->next == NULL){
            return 0; //如果节点为空或没有下一个节点，返回0
        }
        else {
            return node->next->val; //返回下一个节点的值
        }
    }

    //删除
    void Delete(int val) {
        //链表为空
        if (head == NULL) return;

        //如果只有一个节点
        if (head->next == NULL) {
            if (head->val == val) {
                delete head;
                head = NULL;
                tail = NULL;
                size--;
            }
            return;
        }

        //当前节点
        ListNode* cur = head;
        //前一个节点
        ListNode* prev = NULL;

        while (cur != NULL) {
            if (cur->val == val) {
                //如果是头节点
                if (prev == NULL) {
                    head = cur->next;
                    //如果是尾节点
                }
                else if (cur->next == NULL) {
                    tail = prev;
                    prev->next = NULL;
                    //如果是中间节点
                }
                else {
                    prev->next = cur->next;
                }
                delete cur; //释放内存
                //更新链表大小
                size--;
                return;
            }
            //更新前一个节点和当前节点
            prev = cur;
            cur = cur->next;
        }
    }


    //删除下一个
    void DeleteNext(int val){
        if (head == NULL){
            return;
        }
        if (head->next == NULL){
            return;
        }

        ListNode* cur = head;
        while (cur != NULL) {
            if (cur->val == val) {
                ListNode* toDelete = cur->next;
                if (toDelete != NULL) {
                    cur->next = toDelete->next;
                    if (toDelete == tail) {
                        tail = cur; //更新尾节点
                    }
                    delete toDelete; //释放内存
                    size--;
                }
                return;
            }
            cur = cur->next;
        }
    }


    //删除下一个
    void DeleteNext(ListNode* node){
        if (node == NULL || node->next == NULL){
            return; //如果节点为空或没有下一个节点，直接返回
        }

        ListNode* toDelete = node->next; //获取下一个节点
        node->next = toDelete->next; //将当前节点的下一个指向下下一个节点
        if (toDelete == tail) {
            tail = node; //如果删除的是尾节点，更新尾节点
        }
        arr[toDelete->val] = NULL; //清除缓存
        delete toDelete; //释放内存
        size--; //更新链表大小
    }




    //获取链表大小
    int GetSize() const {
        return size;
    }


    //析构函数
    ~List() {
        ListNode* cur = head;
        while (cur != NULL) {
            ListNode* nextNode = cur->next;
            delete cur; //释放当前节点内存
            cur = nextNode; //移动到下一个节点
        }
        head = NULL; //清空头节点
        tail = NULL; //清空尾节点
        size = 0; //重置大小
    }

};

/**
 * https://www.luogu.com.cn/problem/B3631
 */
int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(NULL);

    List list;

    

    int q;
    std::cin >> q;

    while(q--){
        int op;
        std::cin >> op;

        if (op == 1){
            int x, y;
            std::cin >> x >> y;
            
            ListNode* node = arr[x];
            if (node == NULL){
                node = list.Find(x);
                if (node == NULL){
                    node = list.Add(x);
                }
                arr[x] = node; //缓存节点
            }
            ListNode* yNode = list.Add(y, node);
            arr[y] = yNode; //缓存节点
        }else if (op ==2){
            int x;
            std::cin >> x;

            ListNode* node = arr[x];

            std::cout << list.FindNext(node) << "\n";
        }else if (op == 3){
            int x;
            std::cin >> x;
            list.DeleteNext(arr[x]);
        }
    }

    return 0;
}